import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, Method } from 'axios'
import { ApiResponse } from '@/types/types'
import { ElMessage, MessageHandler } from 'element-plus'
import apiConfig from '@/api/config'
import { MessageType } from '@/types/types'
import { useRouter } from 'vue-router'
import Cookie from './cookie'
import { TODOAUTH } from '@/config/constant'

class Request {

  public static axiosInstance: AxiosInstance

  private static messageHandler: MessageHandler

  /**
   * 打开请求错误提示信息
   */
  private static openMessageBox(type: MessageType, message: string) {
    this.messageHandler = ElMessage({
      type,
      message
    })
  } 

  /**
   * 错误处理
   */
  private static handleErrorCode(errCode: number) {
    switch (errCode) {
      case 10002:
        this.openMessageBox('warning', '登录已过期，请重新登录!')
        Cookie.remove(TODOAUTH)
        setTimeout(() => { window.location.href = '/login' }, 1000);
        break;
      case 403:
        this.openMessageBox('error', 'Unauthorized')
        break
      case 404:
        this.openMessageBox('error', '404 Not Found !')
        break
      case 500:
        this.openMessageBox('error', 'Server Error !')
    }
  }
  
  /**
   * 注册请求拦截器
   */
  private static initInterceptors() {
    this.axiosInstance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

    /**
     * 请求拦截器
     */
    this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
      return config
    }, error => {
      console.error(error)
      this.openMessageBox('error', error)
    })

    /**
     * 响应拦截器
     */
    this.axiosInstance.interceptors.response.use((response: AxiosResponse<ApiResponse>) => {
      return response
    }, err => {
      console.log(err)
      this.handleErrorCode(err.response.data.code || err.response.status)
    })
  }

  static {
    this.axiosInstance = axios.create({
      baseURL: apiConfig.BASE_URL,
      timeout: apiConfig.TIME_OUT
    })
    this.initInterceptors()
  }
}

export default function request (url: string, method: Method, data?: any) {
  return new Promise<ApiResponse>((resolve, reject) => {
    Request.axiosInstance({
      method,
      url,
      [method.toLowerCase() === 'get' ? 'params' : 'data']: data
    }).then(
      (resp: AxiosResponse<ApiResponse>) => {
        resolve(resp?.data)
      },
      (err: Error) => {
        reject(err)
      }
    )
  })
}
